home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / xmesa1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  45.3 KB  |  1,528 lines

  1. /* $Id: xmesa1.c,v 1.16 1997/01/31 20:40:46 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: xmesa1.c,v $
  26.  * Revision 1.16  1997/01/31 20:40:46  brianp
  27.  * in XMesaCreateVisual copy viinfo to vishandle
  28.  *
  29.  * Revision 1.15  1997/01/29 19:21:39  brianp
  30.  * save a copy of the visinfo passed to XMesaCreateVisual() per Wolfram Gloger
  31.  *
  32.  * Revision 1.14  1997/01/03 23:56:13  brianp
  33.  * pick a better dithered color in xmesa_color_to_pixel() per Michael Pichler
  34.  *
  35.  * Revision 1.13  1996/12/20 20:40:55  brianp
  36.  * added .30 : .59 : .11 color weighting to noFaultXAllocColor()
  37.  *
  38.  * Revision 1.12  1996/12/03 21:40:24  brianp
  39.  * remove the shared memory ID if shmat() fails in alloc_shm_back_buffer()
  40.  *
  41.  * Revision 1.11  1996/12/03 21:12:30  brianp
  42.  * setup for 8-bit True/DirectColor no longer needs a colormap
  43.  *
  44.  * Revision 1.10  1996/11/21 03:42:44  brianp
  45.  * fixed 24/32 bit per pixel bug, added check for MESA_INFO env var
  46.  *
  47.  * Revision 1.9  1996/11/09 01:44:27  brianp
  48.  * noFaultXAllocColor() was reading from free()'d space!
  49.  *
  50.  * Revision 1.8  1996/10/22 02:44:41  brianp
  51.  * now uses DITHER_SETUP and LOOKUP_SETUP macros
  52.  *
  53.  * Revision 1.7  1996/09/27 17:10:38  brianp
  54.  * index_bits now stored in the XMesaVisual struct
  55.  *
  56.  * Revision 1.6  1996/09/27 01:31:29  brianp
  57.  * removed unused variables
  58.  *
  59.  * Revision 1.5  1996/09/20 02:55:39  brianp
  60.  * updated profiling code
  61.  *
  62.  * Revision 1.4  1996/09/19 03:42:05  brianp
  63.  * added XMesaGetCurrentBuffer
  64.  *
  65.  * Revision 1.3  1996/09/19 03:16:04  brianp
  66.  * new X/Mesa interface with XMesaContext, XMesaVisual, and XMesaBuffer types
  67.  *
  68.  * Revision 1.2  1996/09/15 14:21:27  brianp
  69.  * use new GLframebuffer and GLvisual types and functions
  70.  *
  71.  * Revision 1.1  1996/09/13 01:38:16  brianp
  72.  * Initial revision
  73.  *
  74.  */
  75.  
  76.  
  77. /*
  78.  * Mesa/X11 interface, part 1.
  79.  *
  80.  * This file contains the implementations of all the XMesa* functions.
  81.  *
  82.  *
  83.  * NOTES:
  84.  *
  85.  * The window coordinate system origin (0,0) is in the lower-left corner
  86.  * of the window.  X11's window coordinate origin is in the upper-left
  87.  * corner of the window.  Therefore, most drawing functions in this
  88.  * file have to flip Y coordinates.
  89.  *
  90.  * Define SHM in the Makefile with -DSHM if you want to compile in support
  91.  * for the MIT Shared Memory extension.  If enabled, when you use an Ximage
  92.  * for the back buffer in double buffered mode, the "swap" operation will
  93.  * be faster.  You must also link with -lXext.
  94.  *
  95.  * Byte swapping:  If the Mesa host and the X display use a different
  96.  * byte order then there's some trickiness to be aware of when using
  97.  * XImages.  The byte ordering used for the XImage is that of the X
  98.  * display, not the Mesa host.
  99.  * The color-to-pixel encoding for True/DirectColor must be done
  100.  * according to the display's visual red_mask, green_mask, and blue_mask.
  101.  * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
  102.  * do byte swapping if needed.  If one wants to directly "poke" the pixel
  103.  * into the XImage's buffer then the pixel must be byte swapped first.  In
  104.  * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
  105.  * and use XPutPixel everywhere except in the implementation of
  106.  * glClear(GL_COLOR_BUFFER_BIT).  We want this function to be fast so
  107.  * instead of using XPutPixel we "poke" our values after byte-swapping
  108.  * the clear pixel value if needed.
  109.  *
  110.  */
  111.  
  112.  
  113. #include <assert.h>
  114. #include <math.h>
  115. #include <stdio.h>
  116. #include <stdlib.h>
  117. #include <string.h>
  118. #include <X11/Xlib.h>
  119. #include <X11/Xutil.h>
  120. #ifdef SHM
  121. #  include <sys/ipc.h>
  122. #  include <sys/shm.h>
  123. #  include <X11/extensions/XShm.h>
  124. #endif
  125. #include "GL/xmesa.h"
  126. #include "xmesaP.h"
  127. #include "context.h"
  128. #include "macros.h"
  129. #include "matrix.h"
  130. #include "types.h"
  131.  
  132.  
  133. XMesaContext XMesa = NULL;
  134.  
  135.  
  136. /*
  137.  * Lookup tables for HPCR pixel format:
  138.  */
  139. static short hpcr_rTbl[256] = {
  140.  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
  141.  24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
  142.  32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
  143.  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
  144.  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
  145.  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
  146.  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
  147.  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
  148. 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
  149. 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
  150. 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
  151. 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
  152. 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
  153. 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
  154. 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
  155. 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
  156. };
  157.  
  158. static short hpcr_gTbl[256] = {
  159.  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  23,
  160.  24,  24,  25,  25,  26,  26,  27,  27,  28,  28,  29,  29,  30,  30,  31,  31,
  161.  32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
  162.  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
  163.  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
  164.  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
  165.  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
  166.  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
  167. 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
  168. 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
  169. 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
  170. 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
  171. 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
  172. 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
  173. 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
  174. 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
  175. };
  176.  
  177. static short hpcr_bTbl[256] = {
  178.  32,  32,  33,  33,  34,  34,  35,  35,  36,  36,  37,  37,  38,  38,  39,  39,
  179.  40,  40,  41,  41,  42,  42,  43,  43,  44,  44,  45,  45,  46,  46,  47,  47,
  180.  48,  48,  49,  49,  50,  50,  51,  51,  52,  52,  53,  53,  54,  54,  55,  55,
  181.  56,  56,  57,  57,  58,  58,  59,  59,  60,  60,  61,  61,  62,  62,  63,  63,
  182.  64,  64,  65,  65,  66,  66,  67,  67,  68,  68,  69,  69,  70,  70,  71,  71,
  183.  72,  72,  73,  73,  74,  74,  75,  75,  76,  76,  77,  77,  78,  78,  79,  79,
  184.  80,  80,  81,  81,  82,  82,  83,  83,  84,  84,  85,  85,  86,  86,  87,  87,
  185.  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
  186.  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
  187. 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
  188. 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
  189. 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
  190. 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
  191. 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
  192. 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
  193. 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
  194. };
  195.  
  196.  
  197.  
  198. /**********************************************************************/
  199. /*****                     X Utility Functions                    *****/
  200. /**********************************************************************/
  201.  
  202.  
  203. /*
  204.  * X/Mesa Error reporting function:
  205.  */
  206. static void error( const char *msg )
  207. {
  208.    fprintf( stderr, "X/Mesa error: %s\n", msg );
  209. }
  210.  
  211.  
  212. /*
  213.  * Return the host's byte order as LSBFirst or MSBFirst ala X.
  214.  */
  215. static int host_byte_order( void )
  216. {
  217.    int i = 1;
  218.    char *cptr = (char *) &i;
  219.    return (*cptr==1) ? LSBFirst : MSBFirst;
  220. }
  221.  
  222.  
  223.  
  224. /*
  225.  * Error handling.
  226.  */
  227. static int mesaXErrorFlag = 0;
  228.  
  229. static int mesaHandleXError( Display *dpy, XErrorEvent *event )
  230. {
  231.     mesaXErrorFlag = 1;
  232.     return 0;
  233. }
  234.  
  235.  
  236. /*
  237.  * Check if the X Shared Memory extension is available.
  238.  * Return:  0 = not available
  239.  *          1 = shared XImage support available
  240.  *          2 = shared Pixmap support available also
  241.  */
  242. static int check_for_xshm( Display *display )
  243. {
  244. #ifdef SHM
  245.    int major, minor, ignore;
  246.    Bool pixmaps;
  247.  
  248.    if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
  249.       if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
  250.      return (pixmaps==True) ? 2 : 1;
  251.       }
  252.       else {
  253.      return 0;
  254.       }
  255.    }
  256.    else {
  257.       return 0;
  258.    }
  259. #else
  260.    /* Can't compile XSHM support */
  261.    return 0;
  262. #endif
  263. }
  264.  
  265.  
  266. /*
  267.  * Return the width and height of the given drawable.
  268.  */
  269. static void get_drawable_size( Display *dpy, Drawable d,
  270.                    unsigned int *width, unsigned int *height )
  271. {
  272.    Window root;
  273.    int x, y;
  274.    unsigned int bw, depth;
  275.  
  276.    XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth );
  277. }
  278.  
  279.  
  280.  
  281. /*
  282.  * Apply gamma correction to an intensity value in [0..max].  Return the
  283.  * new intensity value.
  284.  */
  285. static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max )
  286. {
  287.    double x = (double) value / (double) max;
  288.    return (GLint) ((GLfloat) max * pow( x, 1.0F/gamma ) );
  289. }
  290.  
  291.  
  292.  
  293. /*
  294.  * Return the true number of bits per pixel for XImages.
  295.  * For example, if we request a 24-bit deep visual we may actually
  296.  * get a 32-bit per pixel XImage.  This function gives us this information.
  297.  * Input:  dpy - the X display
  298.  *         visinfo - desribes the visual to be used for XImages
  299.  * Return:  true number of bits per pixel for XImages
  300.  */
  301. static int bits_per_pixel( Display *dpy, XVisualInfo *visinfo )
  302. {
  303.    XImage *img;
  304.    int bitsPerPixel;
  305.    /* Create a temporary XImage */
  306.    img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
  307.                        ZPixmap, 0,           /*format, offset*/
  308.                        (char*) malloc(8),    /*data*/
  309.                        1, 1,                 /*width, height*/
  310.                        32,                   /*bitmap_pad*/
  311.                        0                     /*bytes_per_line*/
  312.                      );
  313.    assert(img);
  314.    /* grab the bits/pixel value */
  315.    bitsPerPixel = img->bits_per_pixel;
  316.    /* free the XImage */
  317.    free( img->data );
  318.    img->data = NULL;
  319.    XDestroyImage( img );
  320.    return bitsPerPixel;
  321. }
  322.  
  323.  
  324.  
  325. /**********************************************************************/
  326. /*****                      Private Functions                     *****/
  327. /**********************************************************************/
  328.  
  329.  
  330. /*
  331.  * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
  332.  * Return:  GL_TRUE if success, GL_FALSE if error
  333.  */
  334. static GLboolean alloc_shm_back_buffer( XMesaBuffer b )
  335. {
  336. #ifdef SHM
  337.    /*
  338.     * We have to do a _lot_ of error checking here to be sure we can
  339.     * really use the XSHM extension.  It seems different servers trigger
  340.     * errors at different points if the extension won't work.  Therefore
  341.     * we have to be very careful...
  342.     */
  343.    GC gc;
  344.    int (*old_handler)( Display *, XErrorEvent * );
  345.  
  346.    b->backimage = XShmCreateImage( b->xm_visual->display,
  347.                                    b->xm_visual->visinfo->visual,
  348.                                    b->xm_visual->visinfo->depth,
  349.                    ZPixmap, NULL, &b->shminfo,
  350.                    b->width, b->height );
  351.    if (b->backimage == NULL) {
  352.       error( "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling." );
  353.       b->shm = 0;
  354.       return GL_FALSE;
  355.    }
  356.  
  357.    b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line
  358.                  * b->backimage->height, IPC_CREAT|0777 );
  359.    if (b->shminfo.shmid < 0) {
  360.       perror("alloc_back_buffer");
  361.       XDestroyImage( b->backimage );
  362.       b->backimage = NULL;
  363.       error( "alloc_back_buffer: Shared memory error (shmget), disabling." );
  364.       b->shm = 0;
  365.       return GL_FALSE;
  366.    }
  367.  
  368.    b->shminfo.shmaddr = b->backimage->data
  369.                       = (char*)shmat( b->shminfo.shmid, 0, 0 );
  370.    if (b->shminfo.shmaddr == (char *) -1) {
  371.       perror("alloc_back_buffer");
  372.       XDestroyImage( b->backimage );
  373.       shmctl( b->shminfo.shmid, IPC_RMID, 0 );
  374.       b->backimage = NULL;
  375.       error("alloc_back_buffer: Shared memory error (shmat), disabling.");
  376.       b->shm = 0;
  377.       return GL_FALSE;
  378.    }
  379.  
  380.    b->shminfo.readOnly = False;
  381.    mesaXErrorFlag = 0;
  382.    old_handler = XSetErrorHandler( mesaHandleXError );
  383.    /* This may trigger the X protocol error we're ready to catch: */
  384.    XShmAttach( b->xm_visual->display, &b->shminfo );
  385.    XSync( b->xm_visual->display, False );
  386.  
  387.    if (mesaXErrorFlag) {
  388.       /* we are on a remote display, this error is normal, don't print it */
  389.       XFlush( b->xm_visual->display );
  390.       mesaXErrorFlag = 0;
  391.       XDestroyImage( b->backimage );
  392.       shmdt( b->shminfo.shmaddr );
  393.       shmctl( b->shminfo.shmid, IPC_RMID, 0 );
  394.       b->backimage = NULL;
  395.       b->shm = 0;
  396.       (void) XSetErrorHandler( old_handler );
  397.       return GL_FALSE;
  398.    }
  399.  
  400.    shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */
  401.  
  402.    /* Finally, try an XShmPutImage to be really sure the extension works */
  403.    gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL );
  404.    XShmPutImage( b->xm_visual->display, b->frontbuffer, gc,
  405.          b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False );
  406.    XSync( b->xm_visual->display, False );
  407.    XFreeGC( b->xm_visual->display, gc );
  408.    (void) XSetErrorHandler( old_handler );
  409.    if (mesaXErrorFlag) {
  410.       XFlush( b->xm_visual->display );
  411.       mesaXErrorFlag = 0;
  412.       XDestroyImage( b->backimage );
  413.       shmdt( b->shminfo.shmaddr );
  414.       shmctl( b->shminfo.shmid, IPC_RMID, 0 );
  415.       b->backimage = NULL;
  416.       b->shm = 0;
  417.       return GL_FALSE;
  418.    }
  419.  
  420.    return GL_TRUE;
  421. #else
  422.    /* Can't compile XSHM support */
  423.    return GL_FALSE;
  424. #endif
  425. }
  426.  
  427.  
  428.  
  429. /*
  430.  * Setup an off-screen pixmap or Ximage to use as the back buffer.
  431.  * Input:  b - the X/Mesa buffer
  432.  */
  433. void xmesa_alloc_back_buffer( XMesaBuffer b )
  434. {
  435.    if (b->db_state==BACK_XIMAGE) {
  436.       /* Deallocate the old backimage, if any */
  437.       if (b->backimage) {
  438. #ifdef SHM
  439.      if (b->shm) {
  440.         XShmDetach( b->xm_visual->display, &b->shminfo );
  441.         XDestroyImage( b->backimage );
  442.         shmdt( b->shminfo.shmaddr );
  443.      }
  444.      else
  445. #endif
  446.        XDestroyImage( b->backimage );
  447.      b->backimage = NULL;
  448.       }
  449.  
  450.       /* Allocate new back buffer */
  451.       if (b->shm==0 || alloc_shm_back_buffer(b)==GL_FALSE) {
  452.      /* Allocate a regular XImage for the back buffer. */
  453.      b->backimage = XCreateImage( b->xm_visual->display,
  454.                                       b->xm_visual->visinfo->visual,
  455.                                       b->xm_visual->visinfo->depth,
  456.                       ZPixmap, 0,   /* format, offset */
  457.                       NULL, b->width, b->height,
  458.                       8, 0 );  /* pad, bytes_per_line */
  459.      if (!b->backimage) {
  460.         error("alloc_back_buffer: XCreateImage failed.");
  461.      }
  462.          b->backimage->data = (char *) malloc( b->backimage->height
  463.                                              * b->backimage->bytes_per_line );
  464.          if (!b->backimage->data) {
  465.             error("alloc_back_buffer: malloc failed.");
  466.             XDestroyImage( b->backimage );
  467.             b->backimage = NULL;
  468.          }
  469.       }
  470.       b->backpixmap = None;
  471.    }
  472.    else if (b->db_state==BACK_PIXMAP) {
  473.       Pixmap old_pixmap = b->backpixmap;
  474.       /* Free the old back pixmap */
  475.       if (b->backpixmap) {
  476.      XFreePixmap( b->xm_visual->display, b->backpixmap );
  477.       }
  478.       /* Allocate new back pixmap */
  479.       b->backpixmap = XCreatePixmap( b->xm_visual->display, b->frontbuffer,
  480.                      b->width, b->height,
  481.                                      b->xm_visual->visinfo->depth );
  482.       b->backimage = NULL;
  483.       /* update other references to backpixmap */
  484.       if (b->buffer==old_pixmap) {
  485.      b->buffer = b->backpixmap;
  486.       }
  487.    }
  488. }
  489.  
  490.  
  491.  
  492. /*
  493.  * A replacement for XAllocColor.  This function should never
  494.  * fail to allocate a color.  When XAllocColor fails, we return
  495.  * the nearest matching color.  If we have to allocate many colors
  496.  * this function isn't too efficient; the XQueryColors() could be
  497.  * done just once.
  498.  * Written by Michael Pichler, Brian Paul, Mark Kilgard
  499.  * Input:  dpy - X display
  500.  *         cmap - X colormap
  501.  *         cmapSize - size of colormap
  502.  * In/Out: color - the XColor struct
  503.  * Output:  exact - 1=exact color match, 0=closest match
  504.  */
  505. static void
  506. noFaultXAllocColor( Display *dpy, Colormap cmap, int cmapSize,
  507.                     XColor *color, int *exact )
  508. {
  509.    XColor *ctable, subColor;
  510.    int i, bestmatch;
  511.    double mindist;       /* 3*2^16^2 exceeds long int precision. */
  512.  
  513.    /* First try just using XAllocColor. */
  514.    if (XAllocColor(dpy, cmap, color)) {
  515.       *exact = 1;
  516.       return;
  517.    }
  518.  
  519.    /* Alloc failed, search for closest match */
  520.  
  521.    /* Retrieve color table entries. */
  522.    /* XXX alloca candidate. */
  523.    ctable = (XColor *) malloc(cmapSize * sizeof(XColor));
  524.    for (i = 0; i < cmapSize; i++) {
  525.       ctable[i].pixel = i;
  526.    }
  527.    XQueryColors(dpy, cmap, ctable, cmapSize);
  528.  
  529.    /* Find best match. */
  530.    bestmatch = -1;
  531.    mindist = 0.0;
  532.    for (i = 0; i < cmapSize; i++) {
  533.       double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
  534.       double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
  535.       double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
  536.       double dist = dr * dr + dg * dg + db * db;
  537.       if (bestmatch < 0 || dist < mindist) {
  538.          bestmatch = i;
  539.          mindist = dist;
  540.       }
  541.    }
  542.  
  543.    /* Return result. */
  544.    subColor.red   = ctable[bestmatch].red;
  545.    subColor.green = ctable[bestmatch].green;
  546.    subColor.blue  = ctable[bestmatch].blue;
  547.    /* Try to allocate the closest match color.  This should only
  548.     * fail if the cell is read/write.  Otherwise, we're incrementing
  549.     * the cell's reference count.
  550.     */
  551.    if (!XAllocColor(dpy, cmap, &subColor)) {
  552.       /* do this to work around a problem reported by Frank Ortega */
  553.       subColor.pixel = (unsigned long) bestmatch;
  554.       subColor.red   = ctable[bestmatch].red;
  555.       subColor.green = ctable[bestmatch].green;
  556.       subColor.blue  = ctable[bestmatch].blue;   
  557.       subColor.flags = DoRed | DoGreen | DoBlue;
  558.    }
  559.    free(ctable);
  560.    *color = subColor;
  561.    *exact = 0;
  562. }
  563.  
  564.  
  565.  
  566. /*
  567.  * Do setup for PF_GRAYSCALE pixel format.
  568.  * Note that buffer may be NULL.
  569.  */
  570. static GLboolean setup_grayscale( XMesaVisual v, XMesaBuffer buffer,
  571.                                   Colormap cmap )
  572. {
  573.    int gray;
  574.    int colorsfailed = 0;
  575.    XColor xcol;
  576.  
  577.    if (v->visinfo->depth<4 || v->visinfo->depth>16) {
  578.       return GL_FALSE;
  579.    }
  580.  
  581.    if (buffer) {
  582.       if (!cmap) {
  583.          return GL_FALSE;
  584.       }
  585.  
  586.       /* Allocate 256 shades of gray */
  587.       for (gray=0;gray<256;gray++) {
  588.          GLint r = gamma_adjust( v->RedGamma,   gray, 255 );
  589.          GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
  590.          GLint b = gamma_adjust( v->BlueGamma,  gray, 255 );
  591.          int exact;
  592.  
  593.          xcol.red   = (r << 8) | r;
  594.          xcol.green = (g << 8) | g;
  595.          xcol.blue  = (b << 8) | b;
  596.          noFaultXAllocColor( v->display, cmap, v->visinfo->colormap_size,
  597.                              &xcol, &exact );
  598.          if (!exact) {
  599.             colorsfailed++;
  600.          }
  601.  
  602.          buffer->color_table[gray] = xcol.pixel;
  603.          buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
  604.          buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
  605.          buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
  606.       }
  607.  
  608.       if (colorsfailed && getenv("MESA_DEBUG")) {
  609.          fprintf( stderr,
  610.                   "Note: %d out of 256 needed colors do not match exactly.\n",
  611.                   colorsfailed );
  612.       }
  613.    }
  614.  
  615. #define WEIGHT
  616. #ifdef WEIGHT
  617.    v->rmult = 30 * 255 / 100;
  618.    v->gmult = 59 * 255 / 100;
  619.    v->bmult = 11 * 255 / 100;
  620. #else
  621.    v->rmult = 255/3;
  622.    v->gmult = 255/3;
  623.    v->bmult = 255/3;
  624. #endif
  625.    v->dithered_pf = PF_GRAYSCALE;
  626.    v->undithered_pf = PF_GRAYSCALE;
  627.    return GL_TRUE;
  628. }
  629.  
  630.  
  631.  
  632. /*
  633.  * Setup RGB rendering for a window with a PseudoColor, StaticColor,
  634.  * or 8-bit TrueColor visual visual.  We try to allocate a palette of 225
  635.  * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
  636.  * color.  While this function was originally designed just for 8-bit
  637.  * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
  638.  * Dithering code contributed by Bob Mercier.
  639.  */
  640. static GLboolean setup_dithered_color( XMesaVisual v, XMesaBuffer buffer,
  641.                                        Window window, Colormap cmap )
  642. {
  643.    int r, g, b, i;
  644.    int colorsfailed = 0;
  645.    XColor xcol;
  646.  
  647.    if (v->visinfo->depth<4 || v->visinfo->depth>16) {
  648.       return GL_FALSE;
  649.    }
  650.  
  651.    if (buffer) {
  652.       if (!cmap) {
  653.          return GL_FALSE;
  654.       }
  655.  
  656.       /* Allocate X colors and initialize color_table[], red_table[], etc */
  657.       for (r = 0; r < _R; r++) {
  658.          for (g = 0; g < _G; g++) {
  659.             for (b = 0; b < _B; b++) {
  660.                int exact;
  661.  
  662.                xcol.red   = gamma_adjust(v->RedGamma,   r*65535/(_R-1), 65535);
  663.                xcol.green = gamma_adjust(v->GreenGamma, g*65535/(_G-1), 65535);
  664.                xcol.blue  = gamma_adjust(v->BlueGamma,  b*65535/(_B-1), 65535);
  665.                noFaultXAllocColor( v->display, cmap, v->visinfo->colormap_size,
  666.                                    &xcol, &exact );
  667.                if (!exact) {
  668.                   colorsfailed++;
  669.                }
  670.  
  671.                i = _MIX( r, g, b );
  672.                buffer->color_table[i] = xcol.pixel;
  673.                buffer->pixel_to_r[xcol.pixel] = r * 255 / (_R-1);
  674.                buffer->pixel_to_g[xcol.pixel] = g * 255 / (_G-1);
  675.                buffer->pixel_to_b[xcol.pixel] = b * 255 / (_B-1);
  676.             }
  677.      }
  678.       }
  679.  
  680.       if (colorsfailed && getenv("MESA_DEBUG")) {
  681.          fprintf( stderr,
  682.                   "Note: %d out of %d needed colors do not match exactly.\n",
  683.                   colorsfailed, _R*_G*_B );
  684.       }
  685.    }
  686.  
  687.    v->rmult = 255;
  688.    v->gmult = 255;
  689.    v->bmult = 255;
  690.    v->dithered_pf = PF_DITHER;
  691.    v->undithered_pf = PF_LOOKUP;
  692.    return GL_TRUE;
  693. }
  694.  
  695.  
  696.  
  697. /*
  698.  * Setup for 8-bit TrueColor dithering.  Very similar to the
  699.  * setup_dithered_color() function.  We use the same color_table[]
  700.  * array and dithering algorithm and macros.
  701.  */
  702. static void setup_8bit_truecolor( XMesaVisual v, XMesaBuffer buffer )
  703. {
  704.    int r, g, b, i;
  705.  
  706.    if (buffer) {
  707.       /* Initialize color_table[], red_table[], etc */
  708.       for (r = 0; r < _R; r++) {
  709.          for (g = 0; g < _G; g++) {
  710.             for (b = 0; b < _B; b++) {
  711.                int red, green, blue, pixel;
  712.  
  713.                /* compute gamma adjusted red,green,blue in [0,255] */
  714.                red   = gamma_adjust(v->RedGamma,   r*255/(_R-1), 255);
  715.                green = gamma_adjust(v->GreenGamma, g*255/(_G-1), 255);
  716.                blue  = gamma_adjust(v->BlueGamma,  b*255/(_B-1), 255);
  717.  
  718.                /* compute pixel value from red, green, blue */
  719.                red   = (red   * v->rmult / 255) << v->rshift;
  720.                green = (green * v->gmult / 255) << v->gshift;
  721.                blue  = (blue  * v->bmult / 255) << v->bshift;
  722.                pixel = red | green | blue;
  723.                assert( pixel < 256 );
  724.  
  725.                i = _MIX( r, g, b );
  726.                buffer->color_table[i] = pixel;
  727.                buffer->pixel_to_r[pixel] = r * 255 / (_R-1);
  728.                buffer->pixel_to_g[pixel] = g * 255 / (_G-1);
  729.                buffer->pixel_to_b[pixel] = b * 255 / (_B-1);
  730.             }
  731.      }
  732.       }
  733.    }
  734.  
  735.    v->rmult = 255;
  736.    v->gmult = 255;
  737.    v->bmult = 255;
  738.    v->dithered_pf = PF_DITHER;
  739.    v->undithered_pf = PF_LOOKUP;
  740. }
  741.  
  742.  
  743.  
  744. /*
  745.  * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
  746.  * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
  747.  * Special dithering tables have to be initialized.
  748.  */
  749. static void setup_8bit_hpcr( XMesaVisual v )
  750. {
  751.    /* HP Color Recovery contributed by:  Alex De Bruyn (ad@lms.be)
  752.     * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
  753.     * on the root window AND the colormap obtainable by XGetRGBColormaps
  754.     * for that atom must be set on the window.  (see also tkInitWindow)
  755.     * If that colormap is not set, the output will look stripy.
  756.     */
  757.  
  758.    /* Setup color tables with gamma correction */
  759.    int i;
  760.    double g;
  761.  
  762.    g = 1.0 / v->RedGamma; 
  763.    for (i=0; i<256; i++) { 
  764.       GLint red = 255.0 * pow( hpcr_rTbl[i]/255.0, g ) + 0.5;
  765.       v->hpcr_rTbl[i] = CLAMP( red, 16, 239 );
  766.    }
  767.  
  768.    g = 1.0 / v->GreenGamma;
  769.    for (i=0; i<256; i++) {
  770.       GLint green = 255.0 * pow( hpcr_gTbl[i]/255.0, g ) + 0.5;
  771.       v->hpcr_gTbl[i] = CLAMP( green, 16, 239 );
  772.    }
  773.  
  774.    g = 1.0 / v->BlueGamma;
  775.    for (i=0; i<256; i++) {
  776.       GLint blue = 255.0 * pow( hpcr_bTbl[i]/255.0, g ) + 0.5;
  777.       v->hpcr_bTbl[i] = CLAMP( blue, 32, 223 );
  778.    }
  779.    v->rmult = 255;
  780.    v->gmult = 255;
  781.    v->bmult = 255;
  782.    v->undithered_pf = PF_HPCR;  /* can't really disable dithering for now */
  783.    v->dithered_pf = PF_HPCR;
  784. }
  785.  
  786.  
  787. /*
  788.  * Setup RGB rendering for a window with a True/DirectColor visual.
  789.  */
  790. static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
  791.                              Window window, Colormap cmap )
  792. {
  793.    unsigned long rmask, gmask, bmask;
  794.    int bitsPerPixel;
  795.  
  796.    /* Compute red multiplier and bit shift */
  797.    v->rshift = 0;
  798.    rmask = v->visinfo->red_mask;
  799.    while ((rmask & 1)==0) {
  800.       v->rshift++;
  801.       rmask = rmask >> 1;
  802.    }
  803.    v->rmult = (GLint) rmask;
  804.  
  805.    /* Compute green multiplier and bit shift */
  806.    v->gshift = 0;
  807.    gmask = v->visinfo->green_mask;
  808.    while ((gmask & 1)==0) {
  809.       v->gshift++;
  810.       gmask = gmask >> 1;
  811.    }
  812.    v->gmult = (GLint) gmask;
  813.  
  814.    /* Compute blue multiplier and bit shift */
  815.    v->bshift = 0;
  816.    bmask = v->visinfo->blue_mask;
  817.    while ((bmask & 1)==0) {
  818.       v->bshift++;
  819.       bmask = bmask >> 1;
  820.    }
  821.    v->bmult = (GLint) bmask;
  822.  
  823.    bitsPerPixel = bits_per_pixel( v->display, v->visinfo );
  824.  
  825.    if (   v->visinfo->red_mask  ==0x0000ff
  826.        && v->visinfo->green_mask==0x00ff00
  827.        && v->visinfo->blue_mask ==0xff0000
  828.        && host_byte_order()==ImageByteOrder(v->display)
  829.        && bitsPerPixel==32
  830.        && sizeof(GLuint)==4
  831.        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
  832.       /* common 24-bit config used on SGI, Sun */
  833.       v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
  834.    }
  835.    else if (v->visinfo->red_mask  ==0xff0000
  836.        &&   v->visinfo->green_mask==0x00ff00
  837.        &&   v->visinfo->blue_mask ==0x0000ff
  838.        && host_byte_order()==ImageByteOrder(v->display)
  839.        && bitsPerPixel==32
  840.        && sizeof(GLuint)==4
  841.        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
  842.       /* common 24-bit config used on Linux, HP, IBM */
  843.       v->undithered_pf = v->dithered_pf = PF_8R8G8B;
  844.    }
  845.    else if (v->visinfo->red_mask  ==0xf800
  846.        &&   v->visinfo->green_mask==0x07e0
  847.        &&   v->visinfo->blue_mask ==0x001f
  848.        && host_byte_order()==ImageByteOrder(v->display)
  849.        && bitsPerPixel==16
  850.        && sizeof(GLushort)==2
  851.        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
  852.       /* 5-6-5 color weight on common PC VGA boards */
  853.       v->undithered_pf = v->dithered_pf = PF_5R6G5B;
  854.    }
  855.    else if (v->visinfo->red_mask  ==0xe0
  856.        &&   v->visinfo->green_mask==0x1c
  857.        &&   v->visinfo->blue_mask ==0x03
  858.        && XInternAtom(v->display, "_HP_RGB_SMOOTH_MAP_LIST", True)) {
  859.       setup_8bit_hpcr( v );
  860.    }
  861.    else if (v->visinfo->depth==8) {
  862.       setup_8bit_truecolor( v, buffer );
  863.    }
  864.    else {
  865.       /* general case (i.e. 12-bit TrueColor, or any gamma correction) */
  866.       GLint i;
  867.       /* setup r,g,btable[] arrays with gamma correction */
  868.       for (i=0;i<=v->rmult;i++) {
  869.          v->r_to_pixel[i] = gamma_adjust(v->RedGamma,   i, v->rmult) << v->rshift;
  870.       }
  871.       for (i=0;i<=v->gmult;i++) {
  872.          v->g_to_pixel[i] = gamma_adjust(v->GreenGamma, i, v->gmult) << v->gshift;
  873.       }
  874.       for (i=0;i<=v->bmult;i++) {
  875.          v->b_to_pixel[i] = gamma_adjust(v->BlueGamma,  i, v->bmult) << v->bshift;
  876.       }
  877.       v->undithered_pf = v->dithered_pf = PF_TRUECOLOR;
  878.    }
  879. }
  880.  
  881.  
  882.  
  883. /*
  884.  * Setup RGB rendering for a window with a monochrome visual.
  885.  */
  886. static void setup_monochrome( XMesaVisual v )
  887. {
  888.    v->rmult = 255;
  889.    v->gmult = 255;
  890.    v->bmult = 255;
  891.    v->dithered_pf = v->undithered_pf = PF_1BIT;
  892. }
  893.  
  894.  
  895.  
  896. /*
  897.  * When a context is "made current" for the first time, we can finally
  898.  * finish initializing the context's visual and buffer information.
  899.  * Input:  v - the XMesaVisual to initialize
  900.  *         b - the XMesaBuffer to initialize
  901.  *         rgb_flag - TRUE = RGBA mode, FALSE = color index mode
  902.  *         window - the window/pixmap we're rendering into
  903.  *         cmap - the colormap associated with the window/pixmap
  904.  * Return:  GL_TRUE=success, GL_FALSE=failure
  905.  */
  906. static GLboolean initialize_visual_and_buffer( XMesaVisual v,
  907.                                                XMesaBuffer b,
  908.                                                GLboolean rgb_flag,
  909.                                                Window window,
  910.                                                Colormap cmap )
  911. {
  912.    XGCValues gcvalues;
  913.  
  914.    if (rgb_flag==GL_FALSE) {
  915.       /* COLOR-INDEXED WINDOW:
  916.        * Even if the visual is TrueColor or DirectColor we treat it as
  917.        * being color indexed.  This is weird but might be useful to someone.
  918.        */
  919.       v->dithered_pf = v->undithered_pf = PF_INDEX;
  920.       v->rmult = v->gmult = v->bmult = 0;
  921.       v->index_bits = v->visinfo->depth;
  922.    }
  923.    else {
  924.       /* RGB WINDOW:
  925.        * We support RGB rendering into almost any kind of visual.
  926.        */
  927.       int xclass;
  928. #if defined(__cplusplus) || defined(c_plusplus)
  929.       xclass = v->visinfo->c_class;
  930. #else
  931.       xclass = v->visinfo->class;
  932. #endif
  933.       if (xclass==TrueColor || xclass==DirectColor) {
  934.      setup_truecolor( v, b, window, cmap );
  935.       }
  936.       else if (xclass==StaticGray && v->visinfo->depth==1) {
  937.      setup_monochrome( v );
  938.       }
  939.       else if (xclass==GrayScale || xclass==StaticGray) {
  940.          if (!setup_grayscale( v, b, cmap )) {
  941.             return GL_FALSE;
  942.          }
  943.       }
  944.       else if ((xclass==PseudoColor || xclass==StaticColor)
  945.                && v->visinfo->depth>=4 && v->visinfo->depth<=16) {
  946.      if (!setup_dithered_color( v, b, window, cmap )) {
  947.             return GL_FALSE;
  948.          }
  949.       }
  950.       else {
  951.      error("XMesa: RGB mode rendering not supported in given visual.");
  952.      return GL_FALSE;
  953.       }
  954.       v->index_bits = 0;
  955.    }
  956.  
  957.    /*
  958.     * If MESA_INFO env var is set print out some debugging info
  959.     * which can help Brian figure out what's going on when a user
  960.     * reports bugs.
  961.     */
  962.    if (getenv("MESA_INFO")) {
  963.       printf("v = %p\n", v);
  964.       printf("dithered pf = %d\n", v->dithered_pf);
  965.       printf("undithered pf = %d\n", v->undithered_pf);
  966.       printf("level = %d\n", v->level);
  967.       printf("depth = %d\n", v->visinfo->depth);
  968.       printf("bits per pixel = %d\n", bits_per_pixel(v->display, v->visinfo));
  969.    }
  970.  
  971.    if (b && window) {
  972.       /* Do window-specific initializations */
  973.  
  974.       /* Window dimensions */
  975.       unsigned int w, h;
  976.       get_drawable_size( v->display, window, &w, &h );
  977.       b->width = w;
  978.       b->height = h;
  979.  
  980.       b->frontbuffer = window;
  981.  
  982.       assert( v->gl_visual );
  983.  
  984.       /* Setup for single/double buffering */
  985.       if (v->gl_visual->DBflag) {
  986.          /* Double buffered */
  987.          b->shm = check_for_xshm( v->display );
  988.          xmesa_alloc_back_buffer( b );
  989.          if (b->db_state==BACK_PIXMAP) {
  990.             b->buffer = b->backpixmap;
  991.          }
  992.          else {
  993.             b->buffer = XIMAGE;
  994.          }
  995.       }
  996.       else {
  997.          /* Single Buffered */
  998.          b->buffer = b->frontbuffer;
  999.       }
  1000.  
  1001.       /* X11 graphics contexts */
  1002.       b->gc1 = XCreateGC( v->display, window, 0, NULL );
  1003.       XSetFunction( v->display, b->gc1, GXcopy );
  1004.       b->gc2 = XCreateGC( v->display, window, 0, NULL );
  1005.       XSetFunction( v->display, b->gc2, GXcopy );
  1006.       /*
  1007.        * Don't generate Graphics Expose/NoExpose events in swapbuffers().
  1008.        * Patch contributed by Michael Pichler May 15, 1995.
  1009.        */
  1010.       gcvalues.graphics_exposures = False;
  1011.       b->cleargc = XCreateGC( v->display, window,
  1012.                               GCGraphicsExposures, &gcvalues);
  1013.       XSetFunction( v->display, b->cleargc, GXcopy );
  1014.  
  1015.       /* Initialize the row buffer XImage for use in write_color_span() */
  1016.       b->rowimage = XCreateImage( v->display,
  1017.                                   v->visinfo->visual,
  1018.                                   v->visinfo->depth,
  1019.                                   ZPixmap, 0,           /*format, offset*/
  1020.                                   (char*) malloc(MAX_WIDTH*4),  /*data*/
  1021.                                   MAX_WIDTH, 1,         /*width, height*/
  1022.                                   32,                   /*bitmap_pad*/
  1023.                                   0                     /*bytes_per_line*/ );
  1024.    }
  1025.  
  1026.    return GL_TRUE;
  1027. }
  1028.  
  1029.  
  1030.  
  1031. /*
  1032.  * Convert an RGBA color to a pixel value.
  1033.  */
  1034. unsigned long xmesa_color_to_pixel( XMesaContext xmesa,
  1035.                                     GLubyte r, GLubyte g, GLubyte b, GLubyte a)
  1036. {
  1037.    switch (xmesa->pixelformat) {
  1038.       case PF_INDEX:
  1039.          return 0;
  1040.       case PF_TRUECOLOR:
  1041.          return PACK_RGB( r, g, b );
  1042.       case PF_8A8B8G8R:
  1043.          return PACK_8A8B8G8R( r, g, b, a );
  1044.       case PF_8R8G8B:
  1045.          return PACK_8R8G8B( r, g, b );
  1046.       case PF_5R6G5B:
  1047.          return PACK_5R6G5B( r, g, b );
  1048.       case PF_DITHER:
  1049.          {
  1050.             DITHER_SETUP;
  1051.             return DITHER( 1, 0, r, g, b );
  1052.          }
  1053.       case PF_1BIT:
  1054.          return (r+g+b) > 382U;   /* 382 = (3*255)/2 */
  1055.       case PF_HPCR:
  1056.          return DITHER_HPCR(1, 1, r, g, b);
  1057.       case PF_LOOKUP:
  1058.          {
  1059.             LOOKUP_SETUP;
  1060.             return LOOKUP( r, g, b );
  1061.          }
  1062.       case PF_GRAYSCALE:
  1063.          return GRAY_RGB( r, g, b );
  1064.       default:
  1065.          abort();
  1066.    }
  1067.    return 0;  /*never get here*/
  1068. }
  1069.  
  1070.  
  1071. /**********************************************************************/
  1072. /*****                       Public Functions                     *****/
  1073. /**********************************************************************/
  1074.  
  1075.  
  1076. /*
  1077.  * When a context is "made current" for the first time, we can finally
  1078.  * finish initializing the context.
  1079.  * Input:  c - the XMesaContext to initialize
  1080.  *         window - the window/pixmap we're rendering into
  1081.  *         cmap - the colormap associated with the window/pixmap
  1082.  * Return:  GL_TRUE=success, GL_FALSE=failure
  1083.  */
  1084. XMesaVisual XMesaCreateVisual( Display *display,
  1085.                                XVisualInfo *visinfo,
  1086.                                GLboolean rgb_flag,
  1087.                                GLboolean alpha_flag,
  1088.                                GLboolean db_flag,
  1089.                                GLboolean ximage_flag,
  1090.                                GLint depth_size,
  1091.                                GLint stencil_size,
  1092.                                GLint accum_size,
  1093.                                GLint level )
  1094. {
  1095.    char *gamma;
  1096.    XMesaVisual v;
  1097.    GLfloat red_scale, green_scale, blue_scale, alpha_scale;
  1098.  
  1099.    /* For debugging only */
  1100.    if (getenv("MESA_XSYNC")) {
  1101.       XSynchronize( display, 1 );    /* This makes debugging X easier */
  1102.    }
  1103.  
  1104.    v = (XMesaVisual) calloc( 1, sizeof(struct xmesa_visual) );
  1105.    if (!v) {
  1106.       return NULL;
  1107.    }
  1108.  
  1109.    v->display = display;
  1110.  
  1111.    /* Save a copy of the XVisualInfo struct because the user may XFree()
  1112.     * the struct but we me need some of the information contained in it
  1113.     * at a later time.
  1114.     */
  1115.    v->visinfo = malloc(sizeof(*visinfo));
  1116.    if(!v->visinfo) {
  1117.       free(v);
  1118.       return NULL;
  1119.    }
  1120.    MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
  1121.  
  1122.    /* Save a copy of the pointer now so we can find this visual again
  1123.     * if we need to search for it in find_glx_visual().
  1124.     */
  1125.    v->vishandle = visinfo;
  1126.  
  1127.    /* check for MESA_GAMMA environment variable */
  1128.    gamma = getenv("MESA_GAMMA");
  1129.    if (gamma) {
  1130.       v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
  1131.       sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
  1132.       if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
  1133.       if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
  1134.       if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
  1135.    }
  1136.    else {
  1137.       v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
  1138.    }
  1139.  
  1140.    v->ximage_flag = ximage_flag;
  1141.    v->level = level;
  1142.  
  1143.    (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
  1144.  
  1145.    red_scale   = (GLfloat) v->rmult;
  1146.    green_scale = (GLfloat) v->gmult;
  1147.    blue_scale  = (GLfloat) v->bmult;
  1148.    alpha_scale = 255.0;
  1149.  
  1150.    v->gl_visual = gl_create_visual( rgb_flag, alpha_flag, db_flag,
  1151.                                     depth_size, stencil_size, accum_size,
  1152.                                     v->index_bits,
  1153.                                     red_scale, green_scale,
  1154.                                     blue_scale, alpha_scale );
  1155.    if (!v->gl_visual) {
  1156.       free(v->visinfo);
  1157.       free(v);
  1158.       return NULL;
  1159.    }
  1160.  
  1161.    return v;
  1162. }
  1163.  
  1164.  
  1165.  
  1166. void XMesaDestroyVisual( XMesaVisual v )
  1167. {
  1168.    gl_destroy_visual( v->gl_visual );
  1169.    free(v->visinfo);
  1170.    free(v);
  1171. }
  1172.  
  1173.  
  1174.  
  1175. /*
  1176.  * Create a new XMesaContext.
  1177.  * Input:  v - XMesaVisual
  1178.  *         share_list - another XMesaContext with which to share display
  1179.  *                      lists or NULL if no sharing is wanted.
  1180.  * Return:  an XMesaContext or NULL if error.
  1181.  */
  1182. XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
  1183. {
  1184.    XMesaContext c;
  1185.  
  1186.    c = (XMesaContext) calloc( 1, sizeof(struct xmesa_context) );
  1187.    if (!c) {
  1188.       return NULL;
  1189.    }
  1190.  
  1191.    c->gl_ctx = gl_create_context( v->gl_visual,
  1192.                                   share_list ? share_list->gl_ctx : NULL,
  1193.                                   (void *) c );
  1194.    if (!c->gl_ctx) {
  1195.       free(c);
  1196.       return NULL;
  1197.    }
  1198.  
  1199.    if (host_byte_order()==ImageByteOrder(v->display)) {
  1200.       c->swapbytes = GL_FALSE;
  1201.    }
  1202.    else {
  1203.       c->swapbytes = GL_TRUE;
  1204.    }
  1205.  
  1206.    c->xm_visual = v;
  1207.    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
  1208.    c->display = v->display;
  1209.    c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
  1210.  
  1211.    return c;
  1212. }
  1213.  
  1214.  
  1215.  
  1216.  
  1217. void XMesaDestroyContext( XMesaContext c )
  1218. {
  1219.    if (c->gl_ctx)  gl_destroy_context( c->gl_ctx );
  1220.  
  1221.    free( c );
  1222. }
  1223.  
  1224.  
  1225.  
  1226. /*
  1227.  * Create a new XMesaBuffer from an X window.
  1228.  * Input:  v - the XMesaVisual
  1229.  *         W - the window
  1230.  * Return:  new XMesaBuffer or NULL if error
  1231.  */
  1232. XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, Window w )
  1233. {
  1234.    XWindowAttributes attr;
  1235.    XMesaBuffer b;
  1236.  
  1237.    b = (XMesaBuffer) calloc( 1, sizeof(struct xmesa_buffer) );
  1238.    if (!b) {
  1239.       return NULL;
  1240.    }
  1241.  
  1242.    XGetWindowAttributes( v->display, w, &attr );
  1243.  
  1244.    b->xm_visual = v;
  1245.    b->pixmap_flag = GL_FALSE;
  1246.    b->cmap = attr.colormap;
  1247.  
  1248.    /* determine back buffer implementation */
  1249.    if (v->gl_visual->DBflag) {
  1250.       if (v->ximage_flag) {
  1251.      b->db_state = BACK_XIMAGE;
  1252.       }
  1253.       else {
  1254.      b->db_state = BACK_PIXMAP;
  1255.       }
  1256.    }
  1257.    else {
  1258.       b->db_state = 0;
  1259.    }
  1260.  
  1261.    b->gl_buffer = gl_create_framebuffer( v->gl_visual );
  1262.    if (!b->gl_buffer) {
  1263.       free(b);
  1264.       return NULL;
  1265.    }
  1266.  
  1267.    if (!initialize_visual_and_buffer( v, b, v->gl_visual->RGBAflag,
  1268.                                       w, attr.colormap )) {
  1269.       gl_destroy_framebuffer( b->gl_buffer );
  1270.       free( b );
  1271.       return NULL;
  1272.    }
  1273.  
  1274.    return b;
  1275. }
  1276.  
  1277.  
  1278.  
  1279. /*
  1280.  * Create a new XMesaBuffer from an X pixmap.
  1281.  * Input:  v - the XMesaVisual
  1282.  *         p - the pixmap
  1283.  *         cmap - the colormap, may be 0 if using a TrueColor or DirectColor
  1284.  *                visual for the pixmap
  1285.  * Return:  new XMesaBuffer or NULL if error
  1286.  */
  1287. XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, Pixmap p, Colormap cmap )
  1288. {
  1289.    XMesaBuffer b;
  1290.  
  1291.    b = (XMesaBuffer) calloc( 1, sizeof(struct xmesa_buffer) );
  1292.    if (!b) {
  1293.       return NULL;
  1294.    }
  1295.  
  1296.    b->xm_visual = v;
  1297.    b->pixmap_flag = GL_TRUE;
  1298.    b->cmap = cmap;
  1299.  
  1300.    /* determine back buffer implementation */
  1301.    if (v->gl_visual->DBflag) {
  1302.       if (v->ximage_flag) {
  1303.      b->db_state = BACK_XIMAGE;
  1304.       }
  1305.       else {
  1306.      b->db_state = BACK_PIXMAP;
  1307.       }
  1308.    }
  1309.    else {
  1310.       b->db_state = 0;
  1311.    }
  1312.  
  1313.    b->gl_buffer = gl_create_framebuffer( v->gl_visual );
  1314.    if (!b->gl_buffer) {
  1315.       free(b);
  1316.       return NULL;
  1317.    }
  1318.  
  1319.    if (!initialize_visual_and_buffer(v, b, v->gl_visual->RGBAflag, p, cmap)) {
  1320.       gl_destroy_framebuffer( b->gl_buffer );
  1321.       free( b );
  1322.       return NULL;
  1323.    }
  1324.  
  1325.    return b;
  1326. }
  1327.  
  1328.  
  1329.  
  1330. /*
  1331.  * Deallocate an XMesaBuffer structure and all related info.
  1332.  */
  1333. void XMesaDestroyBuffer( XMesaBuffer b )
  1334. {
  1335.    if (b->gc1)  XFreeGC( b->xm_visual->display, b->gc1 );
  1336.    if (b->gc2)  XFreeGC( b->xm_visual->display, b->gc2 );
  1337.    if (b->cleargc)  XFreeGC( b->xm_visual->display, b->cleargc );
  1338.  
  1339.    if (b->backimage) {
  1340. #ifdef SHM
  1341.        if (b->shm) {
  1342.        XShmDetach( b->xm_visual->display, &b->shminfo );
  1343.        XDestroyImage( b->backimage );
  1344.        shmdt( b->shminfo.shmaddr );
  1345.        }
  1346.        else
  1347. #endif
  1348.        XDestroyImage( b->backimage );
  1349.    }
  1350.    if (b->backpixmap) {
  1351.       XFreePixmap( b->xm_visual->display, b->backpixmap );
  1352.    }
  1353.    if (b->rowimage) {
  1354.       free( b->rowimage->data );
  1355.       b->rowimage->data = NULL;
  1356.       XDestroyImage( b->rowimage );
  1357.    }
  1358.  
  1359.    gl_destroy_framebuffer( b->gl_buffer );
  1360.    free(b);
  1361. }
  1362.  
  1363.  
  1364.  
  1365. /*
  1366.  * Bind buffer b to context c and make c the current rendering context.
  1367.  */
  1368. GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
  1369. {
  1370.    if ((c && !b) || (!c && b)) {
  1371.       return GL_FALSE;
  1372.    }
  1373.  
  1374.    if (c) {
  1375.       c->xm_buffer = b;
  1376.  
  1377.       gl_make_current( c->gl_ctx, b->gl_buffer );
  1378.       XMesa = c;
  1379.  
  1380.       xmesa_setup_DD_pointers( c->gl_ctx );
  1381.  
  1382.       if (c->gl_ctx->Viewport.Width==0) {
  1383.      /* initialize viewport to window size */
  1384.      gl_Viewport( c->gl_ctx, 0, 0, b->width, b->height );
  1385.      c->gl_ctx->Scissor.Width = b->width;
  1386.      c->gl_ctx->Scissor.Height = b->height;
  1387.       }
  1388.  
  1389.       if (c->xm_visual->gl_visual->RGBAflag) {
  1390.          /*
  1391.           * Must recompute and set these pixel values because colormap
  1392.           * can be different for different windows.
  1393.           */
  1394.          c->pixel = xmesa_color_to_pixel( c, c->red, c->green,
  1395.                                           c->blue, c->alpha );
  1396.          XSetForeground( c->display, c->xm_buffer->gc1, c->pixel );
  1397.          c->clearpixel = xmesa_color_to_pixel( c,
  1398.                                                c->clearcolor[0],
  1399.                                                c->clearcolor[1],
  1400.                                                c->clearcolor[2],
  1401.                                                c->clearcolor[3] );
  1402.          XSetForeground( c->display, c->xm_buffer->cleargc, c->clearpixel );
  1403.       }
  1404.  
  1405.    }
  1406.    else {
  1407.       /* Detach */
  1408.       gl_make_current( NULL, NULL );
  1409.       XMesa = NULL;
  1410.    }
  1411.    return GL_TRUE;
  1412. }
  1413.  
  1414.  
  1415.  
  1416. XMesaContext XMesaGetCurrentContext( void )
  1417. {
  1418.    return XMesa;
  1419. }
  1420.  
  1421.  
  1422.  
  1423. XMesaBuffer XMesaGetCurrentBuffer( void )
  1424. {
  1425.    if (XMesa) {
  1426.       return XMesa->xm_buffer;
  1427.    }
  1428.    else {
  1429.       return 0;
  1430.    }
  1431. }
  1432.  
  1433.  
  1434.  
  1435. /*
  1436.  * Copy the back buffer to the front buffer.  If there's no back buffer
  1437.  * this is a no-op.
  1438.  */
  1439. void XMesaSwapBuffers( XMesaBuffer b )
  1440. {
  1441. #ifdef PROFILE
  1442.    GLdouble t0 = gl_time();
  1443. #endif
  1444.    if (b->db_state) {
  1445.       if (b->backimage) {
  1446.      /* Copy Ximage from host's memory to server's window */
  1447. #ifdef SHM
  1448.      if (b->shm) {
  1449.         XShmPutImage( b->xm_visual->display, b->frontbuffer,
  1450.               b->cleargc,
  1451.               b->backimage, 0, 0,
  1452.               0, 0, b->width, b->height, False );
  1453.         /* wait for finished event??? */
  1454.      }
  1455.      else
  1456. #endif
  1457.          {
  1458.             XPutImage( b->xm_visual->display, b->frontbuffer,
  1459.                        b->cleargc,
  1460.                        b->backimage, 0, 0,
  1461.                        0, 0, b->width, b->height );
  1462.          }
  1463.       }
  1464.       else {
  1465.      /* Copy pixmap to window on server */
  1466.      XCopyArea( b->xm_visual->display,
  1467.             b->backpixmap,   /* source drawable */
  1468.             b->frontbuffer,  /* dest. drawable */
  1469.             b->cleargc,
  1470.             0, 0, b->width, b->height,  /* source region */
  1471.             0, 0                 /* dest region */
  1472.            );
  1473.       }
  1474.    }
  1475.    XSync( b->xm_visual->display, False );
  1476. #ifdef PROFILE
  1477.    XMesa->gl_ctx->SwapCount++;
  1478.    XMesa->gl_ctx->SwapTime += gl_time() - t0;
  1479. #endif
  1480. }
  1481.  
  1482.  
  1483.  
  1484. /*
  1485.  * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
  1486.  * is a way to get "under the hood" of X/Mesa so one can manipulate the
  1487.  * back buffer directly.
  1488.  * Output:  pixmap - pointer to back buffer's Pixmap, or 0
  1489.  *          ximage - pointer to back buffer's XImage, or NULL
  1490.  * Return:  GL_TRUE = context is double buffered
  1491.  *          GL_FALSE = context is single buffered
  1492.  */
  1493. GLboolean XMesaGetBackBuffer( XMesaBuffer b, Pixmap *pixmap, XImage **ximage )
  1494. {
  1495.    if (b->db_state) {
  1496.       if (pixmap)  *pixmap = b->backpixmap;
  1497.       if (ximage)  *ximage = b->backimage;
  1498.       return GL_TRUE;
  1499.    }
  1500.    else {
  1501.       *pixmap = 0;
  1502.       *ximage = NULL;
  1503.       return GL_FALSE;
  1504.    }
  1505. }
  1506.  
  1507.  
  1508.  
  1509. void XMesaFlush( XMesaContext c )
  1510. {
  1511.    XSync( c->xm_visual->display, False );
  1512. }
  1513.  
  1514.  
  1515.  
  1516. const char *XMesaGetString( XMesaContext c, int name )
  1517. {
  1518.    if (name==XMESA_VERSION) {
  1519.       return "2.0";
  1520.    }
  1521.    else if (name==XMESA_EXTENSIONS) {
  1522.       return "";
  1523.    }
  1524.    else {
  1525.       return NULL;
  1526.    }
  1527. }
  1528.